<?php

namespace Yousheng\Ku;

use ArrayAccess;
use Cable8mm\LaravelDatabaseToolbox\Interfaces\ProviderInterface;
use Cable8mm\LaravelDatabaseToolbox\Support\Path;
use Exception;
use Illuminate\Database\Connection;
use InvalidArgumentException;
use PDO;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use SplQueue;

/**
 * Database Object.
 */
final class Ku implements ArrayAccess
{


    private static ?Ku $instance = null;
    private static ?Connection $adminConnection = null;
    private static ?array $adminConnectionConfig = [];
    public const DEFAULT_TABLES = [
        'migrations',
        'users',
        'password_reset_tokens',
        'sessions', // 上面三个在 create_user_table.php 中创建
        'cache',
        'cache_locks', // 上面三个在 create_cache_table.php 中创建
        'jobs',
        'job_batches',
        'failed_jobs', // 上面三个在 create_jobs_table.php 中创建
        'action_events', // nova
        'nova_notifications', //nova
        'nova_pending_field_attachments', //nova
        'nova_field_attachments', //nova
        'password_resets', // /framework/tests/Database/migrations/one/2016_01_01_100000_create_password_resets_table.php中创建
    ];

    /**
     * @var array<\Yousheng\Ku\Table> Table array.
     */
    private array $tables = [];
    private PDO $pdo;
    /**
     * prevent the instance from being cloned (which would create a second instance of it)
     * 使用 Ku::getInstance() 来获取实例
     */
    private function __construct() {}
    private function __clone() {}
    public function __wakeup()
    {
        throw new Exception("Cannot unserialize a singleton.");
    }

    public static function getInstance(): Ku
    {
        if (self::$instance === null) {
            self::$instance = (new static());
        }
        return self::$instance;
    }

    public static function make(): static
    {
        // dd(debug_print_backtrace());
        if (self::$instance === null) {
            self::$instance = new static;
        }

        return self::$instance;
    }

    public function addPdo(PDO $pdo): self
    {
        $this->pdo = $pdo;
        return $this;
    }
    public function getPdo(): PDO
    {
        return $this->pdo;
    }

    /**
     * 具有管理员权限的数据库连接,用于创建数据库,表等
     */
    public static function getAdminConnection(): Connection
    {
        if (empty(self::$adminConnectionConfig)) {
            throw new Exception('Please set admin connection config first');
        }
        if (self::$adminConnection === null) {
            Config::set('database.connections.admin', self::$adminConnectionConfig);
            // dd(self::$adminConnectionConfig);
            self::$adminConnection = DB::connectUsing(config: self::$adminConnectionConfig, name: 'admin');
        }
        return self::$adminConnection;
    }
    public static function setAdminConnectioConfig(array $connection): void
    {
        self::$adminConnectionConfig = $connection;
    }

    public static function getDefaultConnection(): Connection
    {
        return DB::connection();
    }

    /**
     * 读取当前connection 配置中数据库中的表
     * $schemaBuilder->getTables()的结果如下，
     * "name" => "sessions"
     * "schema" => "tiku2025ceshi2"
     * "schema_qualified_name" => "tiku2025ceshi2.sessions"
     * "size" => 16384
     * "comment" => ""
     * "collation" => "utf8mb4_unicode_ci"
     * "engine" => "InnoDB"
     */
    public static function getTablesViaSchema(?Connection $connection = null)
    {
        // $connection->getDoctrineSchemaManager()->listTableNames() // laravel12中不再支持  
        $schemaBuilder = $connection ? $connection->getSchemaBuilder() : app('db.schema');
        return collect($schemaBuilder->getTables())->map(function ($table) {
            return $table['name'];
        })->all();
    }

    /**
     * connection 获取指定数据库所有表
     * mysql> show tables;
     * +-----------------------------+
     * | Tables_in_demo_lernen       |
     * +-----------------------------+
     * | account_settings            |
     * | addons                      |
     * | addresses                   |
     * +-----------------------------+
     * $connection->select('SHOW TABLES')，返回一个数组，数组里每个元素都代表数据库中的一张表，并且元素以对象的形式呈现，对象会有一个名为 Tables_in_<数据库> 的属性
     * Array(
     *     [0] => stdClass Object(
     *         [Tables_in_demo_lernen] => account_settings
     *     )* 

     *     [1] => stdClass Object(
     *         [Tables_in_demo_lernen] => addons
     *     )* 

     *     [2] => stdClass Object(
     *         [Tables_in_demo_lernen] => addresses
     *     )
     * )
     */
    public static function getTablesViaRaw(Connection $connection, String $databaseName)
    {
        $result = $connection->select('SHOW TABLES');
        return  collect($result)->map(function ($table) use ($databaseName) {
            return $table->{'Tables_in_' . $databaseName};
        })->all();
    }
    /**
     * $schemaBuilder->getColumns($tableName) 结果如下
     * array:4 [
     *     0 => array:9 [
     *         "name" => "id"
     *         "type_name" => "bigint"
     *         "type" => "bigint unsigned"
     *         "collation" => null
     *         "nullable" => false
     *         "default" => null
     *         "auto_increment" => true
     *         "comment" => null
     *         "generation" => null
     *     ]
     * ]
     * $schemaBuilder->getColumnListing($tableName) 结果如下
     * array:4 [
     *     0 => "id"
     *     1 => "user_id"
     *     2 => "meta_key"
     *     3 => "meta_value"
     * ]
     */

    public static function getColumnssViaSchema(?Connection $connection = null, String $tableName, $onlyName = false)
    {
        $schemaBuilder = $connection ? $connection->getSchemaBuilder() : app('db.schema');
        $method = $onlyName ? 'getColumnListing' : 'getColumns';
        $result = $schemaBuilder->{$method}($tableName);
        if ($onlyName) {
            return $result; // 只返回表的所有列名
        }
        return collect($result)->map(function ($col) {
            //列9个属性 name,type_name,type,collation,nullable,default,auto_increment,comment,generation,
            unset($col['collation'], $col['generation']); // 删除排序规则和生成列
            return $col;
        })->all();
    }
    /**
     * SHOW FULL COLUMNS FROM 表名，返回结果如下，与$schemaBuilder返回的结果有些差异
     * array:4 [
     *   0 => array:9 [
     *     "Field" => "id"
     *     "Type" => "bigint unsigned"
     *     "Collation" => null                               // full
     *     "Null" => "NO"
     *     "Key" => "PRI"
     *     "Default" => null
     *     "Extra" => "auto_increment"
     *     "Privileges" => "select,insert,update,references" // full
     *     "Comment" => ""                                   // full
     *   ]
 
     */
    public static function getColumnssViaRaw(?Connection $connection = null, String $tableName)
    {
        //$connection->getPdo()->query('SHOW FULL COLUMNS FROM `' . $tableName . '`')->fetchAll(PDO::FETCH_ASSOC); //返回关联数组组成的数组
        //$connection->getPdo()->query('SHOW FULL COLUMNS FROM `' . $tableName . '`')->fetchAll(PDO::FETCH_OBJ); // 返回由对象组成的数组
        $connection->select('SHOW FULL COLUMNS FROM `' . $tableName . '`'); // 返回结果同上
    }

    /**
     *  $schemaBuilder->getForeignKeys($tableName)结果如下
     *  Array(
     * [name] => social_profiles_user_id_foreign
     * [columns] => Array(
     *         [0] => user_id
     *     )
     * [foreign_schema] => demo_lernen
     * [foreign_table] => users
     * [foreign_columns] => Array(
     *         [0] => id
     *     )
     * [on_update] => no action
     * [on_delete] => cascade
     * )
     */
    public static function getForeignKeysViaSchema(?Connection $connection = null, $tableName)
    {
        $schemaBuilder = $connection ? $connection->getSchemaBuilder() : app('db.schema');
        return $schemaBuilder->getForeignKeys($tableName);
    }


    /* 
     外键信息：数据库information_schema，表 KEY_COLUMN_USAGE 中读取
     规则：数据库information_schema，表 REFERENTIAL_CONSTRAINTS 中读取
    Array(
        [CONSTRAINT_CATALOG] => def
        [CONSTRAINT_SCHEMA] => demo_lernen
        [CONSTRAINT_NAME] => social_profiles_user_id_foreign
        [TABLE_CATALOG] => def
        [TABLE_SCHEMA] => demo_lernen
        [TABLE_NAME] => social_profiles
        [COLUMN_NAME] => user_id
        [ORDINAL_POSITION] => 1
        [POSITION_IN_UNIQUE_CONSTRAINT] => 1
        [REFERENCED_TABLE_SCHEMA] => demo_lernen
        [REFERENCED_TABLE_NAME] => users 外键所引用的表名不为空
        [REFERENCED_COLUMN_NAME] => id
    ) 

        SELECT 
            kcu.table_schema AS 源表所在数据库模式,
            kcu.table_name AS 源表名称,
            kcu.column_name AS 源表外键列名,
            kcu.referenced_table_schema AS 目标表所在数据库模式,
            kcu.referenced_table_name AS 目标表名称,
            kcu.referenced_column_name AS 目标表主键列名,
            rc.update_rule AS 更新规则,
            rc.delete_rule AS 删除规则
        FROM 
            INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
        JOIN 
            INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc 
        ON 
            kcu.constraint_name = rc.constraint_name  
            AND kcu.table_schema = rc.table_schema
        WHERE 
            kcu.table_schema = DATABASE()  -- 仅获取当前数据库中的信息
            AND kcu.referenced_table_name IS NOT NULL;  -- 仅获取外键约束信息
    */
    public static function getForeignKeysViaRaw($connection, $tableName)
    {
        // $connection->getPdo()->query('SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_NAME = "' . $tableName . '" AND TABLE_SCHEMA = "' . $database . '" AND REFERENCED_TABLE_NAME IS NOT NULL')->fetchAll(PDO::FETCH_ASSOC);
        // $connection->select('SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_NAME = "' . $tableName . '" AND TABLE_SCHEMA = "' . $database . '" AND REFERENCED_TABLE_NAME IS NOT NULL');

    }

    public function initTables($database, $table = null, $admin = null): Ku
    {
        echo "正在获取数据库 {$database} 的表信息...\n";
        $connection = $admin ? $this->getAdminConnection() : $this->getDefaultConnection(); // $connection->getConfig()

        $tables = is_null($table)
            ? static::getTablesViaRaw($connection, $database)
            : [$table];
        foreach ($tables as $tableName) {
            echo "正在获取表 {$tableName} 的列、外键、索引信息...\n";
            // 列
            $columns = $connection->getPdo()->query('SHOW FULL COLUMNS FROM `' . $tableName . '`')->fetchAll(PDO::FETCH_ASSOC);
            $columnsObject = array_map(
                fn(array $column) => new Column(...self::map($column + ['tableName' => $tableName])),
                $columns
            );

            // 外键
            $templateGetForeignConstraint = <<<EOT
            SELECT
                a_.CONSTRAINT_NAME,
                a_.TABLE_NAME,
                a_.COLUMN_NAME,
                a_.REFERENCED_TABLE_NAME,
                a_.REFERENCED_COLUMN_NAME,
                b_.UPDATE_RULE,
                b_.DELETE_RULE
            FROM
                information_schema.`KEY_COLUMN_USAGE` AS a_
            INNER JOIN
                information_schema.REFERENTIAL_CONSTRAINTS AS b_
            ON a_.CONSTRAINT_NAME = b_.CONSTRAINT_NAME AND a_.CONSTRAINT_SCHEMA=b_.CONSTRAINT_SCHEMA AND a_.TABLE_NAME = b_.TABLE_NAME
            WHERE a_.CONSTRAINT_SCHEMA='%s' AND a_.TABLE_NAME = '%s' ;
            EOT;
            $sql = sprintf($templateGetForeignConstraint, $database, $tableName);

            // $foreignKeys = $connection->getPdo()->query('SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_NAME = "' . $tableName . '" AND TABLE_SCHEMA = "' . $database . '" AND REFERENCED_TABLE_NAME IS NOT NULL')->fetchAll(PDO::FETCH_ASSOC);
            $foreignKeys = $connection->getPdo()->query($sql)->fetchAll(PDO::FETCH_ASSOC);
            /*  array:1 [
                0 => array:7 [
                  "CONSTRAINT_NAME" => "account_settings_user_id_foreign"
                  "TABLE_NAME" => "account_settings"
                  "COLUMN_NAME" => "user_id"
                  "REFERENCED_TABLE_NAME" => "users"
                  "REFERENCED_COLUMN_NAME" => "id"
                  "UPDATE_RULE" => "NO ACTION"
                  "DELETE_RULE" => "NO ACTION"
                ]
              ]  */

            $foreignKeysObject = array_map(
                fn(array $key) => new ForeignKey(...self::mapForeignKeys($key)),
                $foreignKeys
            );
            // 索引
            $indexes = $connection->getSchemaBuilder()->getIndexes($tableName);
            $indexesObject = array_map(fn(array $key) => new Index(...array_merge($key, ['table' => $tableName])), $indexes);
            $this->tables[$tableName] = new Table($tableName, $columnsObject, $foreignKeysObject, $indexesObject, $database);
        }
        return self::getInstance();
    }

    /**
     * 获取 PDO 连接实例，用于执行 SQL 语句。
     * @param  string $host
     * @param  integer $port
     * @param  string $username
     * @param  string $password
     * @return PDO
     */
    public static function getPDOConnection($host, $port, $username, $password)
    {
        return new PDO(sprintf('mysql:host=%s;port=%d;', $host, $port), $username, $password);
    }
    public function getTables(): array
    {
        return $this->tables;
    }
    public function getTable(string $tablename): ?Table
    {
        if (!isset($this->tables[$tablename])) {
            throw new InvalidArgumentException(sprintf('Table %s not found', $tablename));
        }
        return $this->tables[$tablename];
    }

    // 实现 ArrayAccess 接口的4个方法
    public function offsetExists($offset): bool
    {
        return isset($this->tables[$offset]);
    }

    public function offsetGet($offset): mixed
    {
        return $this->tables[$offset] ?? null;
    }

    public function offsetSet($offset, $value): void
    {
        if (is_null($offset)) {
            $this->tables[] = $value;
        } else {
            $this->tables[$offset] = $value;
        }
    }

    public function offsetUnset($offset): void
    {
        unset($this->tables[$offset]);
    }
    public static function map(array $column, ?string $table = null, ?Ku $ku = null): array
    {
        //     0 => array:9 [
        //       "Field" => "id"
        //       "Type" => "bigint unsigned"
        //       "Collation" => null
        //       "Null" => "NO"
        //       "Key" => "PRI"
        //       "Default" => null
        //       "Extra" => "auto_increment"
        //       "Privileges" => "select,insert,update,references"
        //       "Comment" => ""
        //     ]
        $bracket = preg_match('/\(/', $column['Type']) ? preg_replace('/.+\(([^)]+)\)/', '\\1', $column['Type']) : null;
        $primaryKey = isset($column['Key']) && $column['Key'] == 'PRI';
        $autoIncrement = isset($column['Extra']) && preg_match('/auto_increment/', $column['Extra']);
        $notNull = isset($column['Null']) ? ($column['Null'] === 'NO') : false;
        $unsigned = (bool) preg_match('/unsigned/', $column['Type']);
        $type = preg_replace('/[( ].+/', '', $column['Type']);
        $tmp = [
            'field' => $column['Field'],
            'type' => $type,
            'unsigned' => $unsigned,
            'autoIncrement' => $autoIncrement,
            'notNull' => $notNull,
            'primaryKey' => $primaryKey,
            'bracket' => $bracket,
            'default' => $column['Default'],
            'extra' => $column['Extra'],
            'tableName' => $column['tableName'],
        ];

        return $tmp;
    }
    // public static function mapForeignKeys(array $foreignKey): array
    // {
    //     return [
    //         'name' => $foreignKey['CONSTRAINT_NAME'],
    //         // 'table' => Str::studly($foreignKey['TABLE_NAME']),
    //         'table' => $foreignKey['TABLE_NAME'],
    //         'column' => $foreignKey['COLUMN_NAME'],
    //         // 'referenced_table' => Str::studly($foreignKey['REFERENCED_TABLE_NAME']),
    //         'referenced_table' => $foreignKey['REFERENCED_TABLE_NAME'],
    //         'referenced_column' => $foreignKey['REFERENCED_COLUMN_NAME'],
    //     ];
    // }
    public static function mapForeignKeys(array $foreignKey): array
    {
        return [
            'name' => $foreignKey['CONSTRAINT_NAME'],
            // 'table' => Str::studly($foreignKey['TABLE_NAME']),
            'table' => $foreignKey['TABLE_NAME'],
            'column' => $foreignKey['COLUMN_NAME'],
            // 'referenced_table' => Str::studly($foreignKey['REFERENCED_TABLE_NAME']),
            'referenced_table' => $foreignKey['REFERENCED_TABLE_NAME'],
            'referenced_column' => $foreignKey['REFERENCED_COLUMN_NAME'],
            'update_rule' => $foreignKey['UPDATE_RULE'],
            'delete_rule' => $foreignKey['DELETE_RULE'],
        ];
    }
    public static function stubPath($name)
    {
        return __DIR__ . '/../stubs/' . $name . ".stub";
    }

    /**
     * 有些问题，待完善，改为拓扑排序
     * @param $original 原始数组
     * @param $associate 关联数组，键依赖于值，所以键得放在值后面
     * @return array
     */
    public static function sortTable($original, $associate)
    {
        $one = array_diff($original, array_keys($associate)); // 孤表，没有主表，这些表先创建，它不依赖其它表，其它表可以依赖它
        $two = [];
        foreach ($associate as $son => $father) {
            // if(in_array($father,$one) && !in_array($son,$one)) continue; // 依赖的表是孤表，它不依赖任何表，跳过
            if (in_array($father, $one)) {
                $two[] = $son;
            }; // 依赖的表是孤表，它不依赖任何表，跳过
            if (in_array($father, $two)) {
                $two[] = $son;
            } else {
                $two[] = $father; //先放主表
                $two[] = $son;   // 再放从表
            }
        }

        return array_merge($one, $two);
    }

    public static function sortedTables($all, $sontofather)
    {
        $one = array_diff($all, array_keys($sontofather)); // 孤表，没有主表，这些表先创建，它不依赖其它表，其它表可以依赖它
        $two = static::topologicalSortKahn($sontofather); // 拓扑排序依赖表
        return array_merge($one, $two);
    }

    public static function topologicalSortKahn($graph)
    {
        // 对原始数据进行整理
        // 'disputes' => ['users', 'users', 'users', 'users'], 表中有4列依赖于users表，只保留一个就行,实际没影响
        // 'ltu_phrases' => ['ltu_phrases', 'ltu_translation_files', 'ltu_translations'],依赖自己的，删除

        // 收集所有节点（处理孤立节点）
        $allNodes = [];
        // 方法一：
        // foreach ($graph as $u => $neighbors) {
        //     $allNodes[] = $u;
        //     $allNodes = array_merge($allNodes, $neighbors);
        // }
        // $allNodes = array_unique($allNodes);

        // 方法二：改为一条语句，代替上面的foreach循环
        //$allNodes = array_unique(array_merge(array_keys($graph) , call_user_func_array('array_merge', array_values($graph))));
        //sort($allNodes);

        // 方法三：使用laravel集合的链式操作
        $allNodes = collect($graph)
            ->keys()
            ->merge(collect($graph)->values()->flatten())
            ->unique()
            ->sort()
            ->all();

        // 初始化入度表
        $inDegree = array_fill_keys($allNodes, 0); // 表名=>0
        // 所有表的入度
        foreach ($graph as $u => $neighbors) {

            foreach ($neighbors as $v) {
                if ($u === $v) { // 'ltu_phrases' => ['ltu_phrases', 'ltu_translation_files', 'ltu_translations'],这种依赖自己
                    continue;
                }
                $inDegree[$v]++;
            }
        }

        // 队列初始化（入度为0的节点）
        $queue = new SplQueue();
        foreach ($inDegree as $node => $degree) {
            if ($degree == 0) $queue->enqueue($node);
        }

        // 也可以使用laravel集合的方法
        //collect($inDegree)->filter(fn($degree) => $degree == 0)->keys()->each(fn($node) => $queue->enqueue($node));

        $sorted = [];
        while (!$queue->isEmpty()) {
            $u = $queue->dequeue();
            $sorted[] = $u;
            // 遍历邻居，更新入度
            foreach ($graph[$u] ?? [] as $v) {
                if($u===$v){ // 自己依赖自己
                    continue;
                }
                $inDegree[$v]--; // 弹出入度为0的元素后，其它元素入度-1
                if ($inDegree[$v] == 0) {
                    $queue->enqueue($v);
                }
            }
        }
        $sorted = array_reverse($sorted); // 顺序颠倒
        // 检测环
        return count($sorted) === count($allNodes) ? $sorted : null;
    }


    public static function topologicalSort($graph)
    {
        /* array:32 [
            "account_settings" => array:1 [
              0 => "users"
            ]
            "addresses" => array:2 [
              0 => "countries"
              1 => "country_states"
            ]
            "country_states" => array:1 [
              0 => "countries"
            ]
            "dispute_conversations" => array:2 [
              0 => "disputes"
              1 => "users"
            ]
            "disputes" => array:4 [
              0 => "users"
              1 => "users"
              2 => "users"
              3 => "users"
            ]
         
          ] */
        $inDegree = [];
        // 计算每个顶点的入度
        foreach ($graph as $node => $neighbors) {
            if (!isset($inDegree[$node])) {
                $inDegree[$node] = 0;
            }
            foreach ($neighbors as $neighbor) {
                if (!isset($inDegree[$neighbor])) {
                    $inDegree[$neighbor] = 0;
                }
                $inDegree[$neighbor]++;
            }
        }
        /*  array:43 [
            "account_settings" => 0
            "users" => 26
            "addresses" => 0
            "countries" => 4
            "country_states" => 1
            "billing_details" => 0
            "blogs" => 0
            "booking_logs" => 0
            "slot_bookings" => 1
            "dispute_conversations" => 0
            "disputes" => 1
            "favourite_users" => 0
            "ltu_phrases" => 1
            "ltu_translation_files" => 1
            "ltu_translations" => 1
            "model_has_permissions" => 0
            "permissions" => 2
            "model_has_roles" => 0
            "roles" => 2
            "order_items" => 0
            "orders" => 1
            "profiles" => 0
            "ratings" => 0
            "role_has_permissions" => 0
            "user_subject_slots" => 1
            "social_profiles" => 0
            "telescope_entries_tags" => 0
            "telescope_entries" => 1
            "user_certificate" => 0
            "user_contacts" => 0
            "user_education" => 0
            "user_experience" => 0
            "user_identity_verifications" => 0
            "user_languages" => 0
            "languages" => 1
            "user_payout_methods" => 0
            "user_subject_group_subjects" => 1
            "subjects" => 1
            "user_subject_groups" => 1
            "subject_groups" => 1
            "user_wallet_details" => 0
            "user_wallets" => 1
            "user_withdrawals" => 0
          ]  */

        // 初始化队列，将入度为 0 的顶点加入队列
        $queue = [];
        foreach ($inDegree as $node => $degree) {
            if ($degree === 0) {
                $queue[] = $node;
            }
        }
        /* array:24 [
            0 => "account_settings"
            1 => "addresses"
            2 => "billing_details"
            3 => "blogs"
            4 => "booking_logs"
            5 => "dispute_conversations"
            6 => "favourite_users"
            7 => "model_has_permissions"
            8 => "model_has_roles"
            9 => "order_items"
            10 => "profiles"
            11 => "ratings"
            12 => "role_has_permissions"
            13 => "social_profiles"
            14 => "telescope_entries_tags"
            15 => "user_certificate"
            16 => "user_contacts"
            17 => "user_education"
            18 => "user_experience"
            19 => "user_identity_verifications"
            20 => "user_languages"
            21 => "user_payout_methods"
            22 => "user_wallet_details"
            23 => "user_withdrawals"
          ] */

        $result = [];
        // 进行拓扑排序
        while (!empty($queue)) {
            $node = array_shift($queue);
            $result[] = $node;
            // 减少相邻顶点的入度
            if (isset($graph[$node])) {
                foreach ($graph[$node] as $neighbor) {
                    $inDegree[$neighbor]--;
                    if ($inDegree[$neighbor] === 0) {
                        $queue[] = $neighbor;
                    }
                }
            }
        }
        echo "结果\n";
        dump($result);

        // 检查是否存在环
        if (count($result) === count($inDegree)) {
            return $result;
        } else {
            return null; // 图中存在环，无法进行拓扑排序
        }
    }
}
